package cn.tohsaka.factory.dockercraft.Interfaces;
import cn.tohsaka.factory.dockercraft.Engines.DBConnectionPool;
import cn.tohsaka.factory.dockercraft.Libraries.Logger;
import cn.tohsaka.factory.eoh.interfaces.DBRequester;
import com.sun.deploy.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import static java.lang.System.out;

/**
 * Created by Xmsoft on 2017/5/29.
 */
public class DInterface {
    List<String> header=new ArrayList<>();
    String table;
    public DInterface(){
        table=this.getTable();
    }
    public String getTable(){
        return null;
    }
    public DInterface parse(ResultSet rs){
        try{
            table=rs.getMetaData().getTableName(1);
            header.clear();

            for(int i=1;i<=rs.getMetaData().getColumnCount();i++){
                header.add(rs.getMetaData().getColumnLabel(i));
            }
            for (Field a : this.getClass().getDeclaredFields()) {
                if(header.contains(a.getName())){
                    a.setAccessible(true);
                    a.set(this,rs.getObject(a.getName()));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
        return this;
    }
    public String toString(){
        try {
            StringBuilder sb=new StringBuilder();
            for (Field a : this.getClass().getDeclaredFields()) {
                String type=a.getType().getName().substring(a.getType().getName().lastIndexOf(".")+1);
                sb.append(String.format("%s %s = %s;\n",type,a.getName(),a.get(this)));
            }
            return sb.toString();
        }catch (Exception e){
            return e.getLocalizedMessage();
        }
    }
    private int prepareUpdateField(Connection con){
        try {
            List<String> fileds=new ArrayList<>();
            List<String> fileds2=new ArrayList<>();
            fileds.addAll(header);
            fileds.remove(getKey());
            StringBuilder sb=new StringBuilder();
            for (String h:fileds){
                fileds2.add(String.format("%s=?",h));
            }
            KV key=getUpdateKey();
            PreparedStatement ps=con.prepareStatement(String.format("UPDATE %s set %s where %s=?",table,StringUtils.join(fileds2,","),key.K));
            int i=1;
            for (String h:fileds){
                ps.setObject(i,this.getClass().getField(h).get(this));
                i++;
            }
            ps.setObject(i,key.V);
            return ps.executeUpdate();
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }
    private String getKey(){
        try{
            for (String h:header){
                if(Modifier.isVolatile(this.getClass().getField(h).getModifiers())){
                    return h;
                }
            }
        }catch (Exception e){e.printStackTrace();}
        return null;
    }
    public ArrayList<KV> getFieldValue(){
        ArrayList<KV> result=new ArrayList<KV>();
        try{
            for(Field f:this.getClass().getFields()){
                result.add(new KV(f.getName(),f.get(this)));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    private KV getUpdateKey(){
        try{
            for(Field f:this.getClass().getFields()){
                if(Modifier.isVolatile(f.getModifiers())){
                    return new KV(f.getName(),f.get(this));
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public boolean save(){
        try{
            return prepareUpdateField(DBConnectionPool.getConnection())>0;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }
    public boolean delete(){
        try{
            KV key=getUpdateKey();
            PreparedStatement ps = DBConnectionPool.getConnection().prepareStatement(String.format("DELETE FROM %s WHERE %s=?",table,key.K));
            ps.setObject(1,key.V);
            return ps.executeUpdate()>0;
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }
    public DInterface refresh(){
        try {
            KV key=getUpdateKey();
            PreparedStatement ps =DBConnectionPool.getConnection().prepareStatement(String.format("SELECT * FROM %s WHERE %s=?",table,key.K));
            ps.setObject(1,key.V);
            ResultSet rs = ps.executeQuery();
            if(rs.next()){
                return this.parse(rs);
            }else{
                return null;
            }
        }catch (Exception e){
            e.printStackTrace();;
        }
        return null;
    }
    public DInterface setTable(String t){
        table=t;
        return this;
    }
    public int Insert(Boolean returnInsertKey){
        ArrayList<KV> fields=getFieldValue();
        StringBuilder sql=new StringBuilder();
        sql.append(String.format("INSERT INTO %s (",(table!=null)?table:this.getClass().getSimpleName().toLowerCase()));
        int i=0;
        int n=1;
        for (KV k:fields){
            if(k.V!=null){
                sql.append(k.K);
                if(i<fields.size()){
                    sql.append(",");
                }
                n++;
            }
            i++;
        }
        if(sql.lastIndexOf(",")==(sql.length()-1)){
            sql.setLength(sql.length()-1);
        }
        sql.append(")");
        sql.append(" VALUES (");
        if(n>0){
            for(int j=1;j<n;++j){
                sql.append("?");
                sql.append(",");
            }
        }
        if(sql.lastIndexOf(",")==(sql.length()-1)){
            sql.setLength(sql.length()-1);
        }
        sql.append(");");
        try {
            out.println(sql.toString());
            PreparedStatement ps;
            if(returnInsertKey) {
                ps = DBConnectionPool.getConnection().prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
            }else{
                ps = DBConnectionPool.getConnection().prepareStatement(sql.toString());
            }
            int h=1;
            for (int l=0;l<fields.size();l++){
                if(fields.get(l).V!=null) {
                    ps.setObject(h, fields.get(l).V);
                    h++;
                }
            }
                int rows = ps.executeUpdate();
                if (returnInsertKey) {

                    ResultSet rs = ps.getGeneratedKeys();
                    if (rs.next()) {
                        return rs.getInt(1);
                    } else {
                        return -1;
                    }

                }
            return rows;
        }catch (Exception e){
            e.printStackTrace();
            return -1;
        }
    }
}
